<!DOCTYPE html>
<html ng-app="myApp">

	<head>
		<meta charset="UTF-8">
		<title>AngularJS 依赖注入</title>
		<!-- 描述：引用baidu静态资源库 -->
		<script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js" type="text/javascript"></script>
	</head>

	<body ng-controller="myController">
		<h2>什么是依赖注入</h2>
		<p>
			wiki 上的解释是：依赖注入（Dependency Injection，简称DI）是一种软件设计模式，在这种模式下，一个或更多的依赖（或服务）被注入（或者通过引用传递）到一个独立的对象（或客户端）中，然后成为了该客户端状态的一部分。 该模式分离了客户端依赖本身行为的创建，这使得程序设计变得松耦合，并遵循了依赖反转和单一职责原则。与服务定位器模式形成直接对比的是，它允许客户端了解客户端如何使用该系统找到依赖
			<h3>一句话 --- 没事你不要来找我，有事我会去找你。</h3>
		</p>
		<div>
			值传递：<input type="text" ng-model="Entity.Name" />
			<br />
			<br /> 计算面积：
			<input type="text" ng-model="Entity.Length" /><input type="button" value="计算" ng-click="BtnCalculate()" />
			<label>{{Entity.Area|number:2}}</label>
		</div>
		<br />
		<h2>依赖注入demo</h2>
		<div>
			<input type="button" value="FactoryDemo" ng-click="BtnFactory()" />
			<input type="button" value="ServiceDemo" ng-click="BtnService()" />
			<h3>对应值</h3>
			<p>{{DemoValue}}</p>
		</div>
	</body>
	<script type="text/javascript" charset="UTF-8">
		//创建模型
		var app = angular.module("myApp", []);

		app.value("DefaultName", "mengweiwang");

		//创建控制器，并注册服务
		app.controller("myController", function($scope, DefaultName, myFactory, myService) {
			$scope.Entity = {};
			$scope.Entity.Name = DefaultName;
			console.log("初始化页面");

			//方式一（直接计算）
			$scope.BtnCalculate = function() {
				//$scope.Entity.Area = $scope.Entity.Length * $scope.Entity.Length;

				//调用Factory计算面积
				$scope.Entity.Area = myFactory.multiply($scope.Entity.Length, $scope.Entity.Length);
			}

			//方式二（创建factory）
			$scope.BtnFactory = function() {
				myFactory.setAge(20);
				var tempValue = myFactory.getAge();

				myFactory.getData().then(function(data) {
					$scope.DemoValue = data; //正确时执行
				}, function(data) {
					alert(data); //错误时执行
				});
			}

			//方式三（创建Service）
			$scope.BtnService = function() {
				console.log(myService.myFunc(255));

				myService.getData().then(function(data) {
					$scope.DemoValue = data; //正确时执行
				}, function(data) {
					alert(data); //错误时执行
				});
			};
		});

		/*
		 * 通过工厂模式创建自定义服务
		 * 在自定义服务里注入服务示例，但不能注入$scope作用域对象。
		 * */
		app.factory("myFactory", function($http, $q) {
			var factory = {};
			//定义一个公有变量
			factory.Name = "求面积";
			factory.multiply = function(a, b) {
				return a * b;
			}

			//定义一个私有变量
			var currentAge;
			factory.setAge = function(newAge) {
				currentAge = newAge;
			}
			factory.getAge = function() {
				return currentAge;
			}

			//请求数据
			factory.getData = function() {
				var d = $q.defer();
				$http.get("/Test.HBuilder/ApiData/gradeJson.txt")
					.success(function(response) {
						d.resolve(response);
					})
					.error(function(error) {
						d.reject(error);
					});
				return d.promise;
			}
			return factory;
		});

		/*
		 * 通过service方式创建自定义服务，相当于new的一个对象
		 */
		app.service('myService', function($http, $q) {
			this.name = "service";
			this.myFunc = function(value) {
				return value.toString(16); //转16进制
			};
			this.getData = function() {
				var d = $q.defer();
				$http.get("/Test.HBuilder/ApiData/campusJson.txt")
					.success(function(response) {
						d.resolve(response);
					})
					.error(function(error) {
						d.reject(error);
					});
				return d.promise;
			};
		});

		/*
		 * JavaScript结构式编程
		 */
		var Person = function(name, age) {
			this.name = name;
			this.age = age;
		};
		Person.prototype.sayName = function() {
			alert("My name is " + this.name + ",I`m " + this.age + " years old");
		};

		var tyler = new Person("Victory23", 29);
		tyler.sayName();
	</script>

</html>